package martian.m4gic.network.smartfox.core
{
	import flash.utils.ByteArray;
	
	import martian.m4gic.data.Ini;
	import martian.m4gic.services.Assets;
	import martian.m4gic.tools.B64;
	import martian.m4gic.tools.Chrono;

	public class Serializer implements Handler
	{
		/* 
			Message typical format:
			[property name length][property name][property type](if string [property length])[property value]
		*/
		
		static private const NUMERIC:int = 0;
		static private const STRING:int = 1;
		
		
		
		
		
		private var hash:Class = B64;
		
		public function Serializer(type:Class = null) { hash = type != null ? type : B64; }
		
		public function encode(data:Object):String
		{
			var raw:ByteArray = new ByteArray();
				raw.writeInt(data.id);
				
				this.join(data, raw);
			
			if (data.cmd == undefined) { data.cmd = -1; }	
			return data.cmd + "," + (hash as Class).encode(raw);
		}
		
		protected function join(data:Object, raw:ByteArray):void
		{
			for(var property:* in data)
			{
				raw.writeUTF(property);
				
				if (data[property] is String)
				{
					raw.writeShort(STRING);
					raw.writeUTF(data[property]);
				}
				else if (!isNaN(data[property]))
				{
					raw.writeShort(NUMERIC);
					raw.writeFloat(data[property]);
				}
			}
		}
		
		public function decode(str:String):Object
		{
			var split:Array = str.split(",");
			str = split[1];
			
			var raw:ByteArray = (hash as Class).decode(str),
				data:Object = new Object();
			
			data.id = raw.readInt();
			data.cmd = parseInt(split[0]);

			this.split(raw, data);
			
			return data;
		}
		
		protected function split(raw:ByteArray, data:Object):void
		{
			var property:String, type:int;
			
			while(raw.bytesAvailable)
			{
				property = raw.readUTF();
				type = raw.readShort();
				
				if (type == STRING)	{ data[property] = raw.readUTF(); }
				else if (type == NUMERIC) { data[property] = raw.readFloat(); }
			}
		}
	}
}